// import com.alibaba.druid.sql.ast.SQLExpr;
// import com.alibaba.druid.sql.ast.SQLHint;
// import com.alibaba.druid.sql.ast.SQLName;
// import com.alibaba.druid.sql.ast.SQLReplaceable;
// import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
// import com.alibaba.druid.sql.ast.expr.SQLListExpr;
// import com.alibaba.druid.sql.visitor.SQLASTVisitor;

#include "SQLValuesTableSource.h"
#include "../../visitor/SQLASTVisitor.h"
#include "../../../utils/listTran.h"
#include "../expr/SQLListExpr.h"

SQLValuesTableSource::SQLValuesTableSource()
{
  values = std::make_shared<std::list<SQLListExpr_ptr>>();
  columns = std::make_shared<std::list<SQLName_ptr>>();
}

SQLListExpr_list_ptr SQLValuesTableSource::getValues()
{
  return values;
}

void SQLValuesTableSource::addValue(SQLListExpr_ptr row)
{
  if (row == nullptr)
  {
    return;
  }

  row->setParent(SharedObject(SQLValuesTableSource));
  values->push_back(row);
}

SQLName_list_ptr SQLValuesTableSource::getColumns()
{
  return columns;
}

void SQLValuesTableSource::addColumn(SQLName_ptr column)
{
  column->setParent(SharedObject(SQLValuesTableSource));
  columns->push_back(column);
}

void SQLValuesTableSource::addColumn(string_ptr column)
{
  addColumn(SQLIdentifierExpr_ptr(new SQLIdentifierExpr(column)));
}

// @Override
void SQLValuesTableSource::accept0(SQLASTVisitor_ptr visitor)
{
  if (visitor->visit(SharedObject(SQLValuesTableSource)))
  {
    SQLObject_list_ptr tmp = ListTran::tran_class<SQLListExpr, SQLObject>(values);
    acceptChild(visitor, tmp);
    SQLObject_list_ptr tmp1 = ListTran::tran_class<SQLName, SQLObject>(columns);
    acceptChild(visitor, tmp1);
  }
  visitor->endVisit(SharedObject(SQLValuesTableSource));
}

// @Override
BOOL_ptr SQLValuesTableSource::isParenthesized()
{
  return parenthesized;
}

// @Override
void SQLValuesTableSource::setParenthesized(BOOL_ptr paren)
{
  this->parenthesized = paren;
}

// @Override
SQLObject_ptr SQLValuesTableSource::clone()
{
  SQLObject_ptr clone_tmp = std::shared_ptr<SQLValuesTableSource>(new SQLValuesTableSource());
  std::shared_ptr<SQLValuesTableSource> x = std::dynamic_pointer_cast<SQLValuesTableSource>(clone_tmp);
  // SQLValuesTableSource x = new SQLValuesTableSource();

  x->setAlias(this->alias);

  for (SQLListExpr_ptr e : *this->values)
  {
    SQLListExpr_ptr e2 = std::dynamic_pointer_cast<SQLListExpr>(e->clone());
    e2->setParent(x);
    x->getValues()->push_back(e2);
  }

  for (SQLName_ptr e : *this->columns)
  {
    SQLName_ptr e2 = std::dynamic_pointer_cast<SQLName>(e->clone());
    e2->setParent(x);
    x->getColumns()->push_back(e2);
  }

  if (this->flashback != nullptr)
  {
    x->setFlashback(std::dynamic_pointer_cast<SQLExpr>(this->flashback->clone()));
  }

  if (this->hints != nullptr)
  {
    for (SQLHint_ptr e : *this->hints)
    {
      SQLHint_ptr e2 = std::dynamic_pointer_cast<SQLHint>(e->clone());
      e2->setParent(std::dynamic_pointer_cast<SQLHint>(x));
      x->getHints()->push_back(e2);
    }
  }

  return x;
}

// @Override
BOOL_ptr SQLValuesTableSource::replace(SQLExpr_ptr expr, SQLExpr_ptr target)
{
  auto it_values = values->begin();
  for (int i = 0; i < values->size(); i++)
  {
    std::advance(it_values, i);
    if ((*it_values) == expr)
    {
      target->setParent(SharedObject(SQLValuesTableSource));
      (*it_values) = std::dynamic_pointer_cast<SQLListExpr>(expr);
      return BOOL::TRUE;
    }
  }

  auto it_columns = columns->begin();
  for (int i = 0; i < columns->size(); i++)
  {
    std::advance(it_columns, i);
    if ((*it_columns) == expr)
    {
      target->setParent(SharedObject(SQLValuesTableSource));
      (*it_columns) = std::dynamic_pointer_cast<SQLName>(expr);
      return BOOL::TRUE;
    }
  }

  return BOOL::FALSE;
}
